package com.bx.implatform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bx.imclient.IMClient;
import com.bx.imcommon.enums.IMCmdType;
import com.bx.imcommon.model.IMPrivateMessage;
import com.bx.imcommon.model.IMSendInfo;
import com.bx.imcommon.model.IMUserInfo;
import com.bx.implatform.contant.FriendApplyStatus;
import com.bx.implatform.dto.friend.AddFriendApplyDTO;
import com.bx.implatform.dto.friend.AddFriendDTO;
import com.bx.implatform.entity.FriendApply;
import com.bx.implatform.entity.PrivateMessage;
import com.bx.implatform.enums.MessageStatus;
import com.bx.implatform.enums.MessageType;
import com.bx.implatform.enums.ResultCode;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.FriendApplyMapper;
import com.bx.implatform.service.IFriendApplyService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.util.SensitiveFilterUtil;
import com.bx.implatform.vo.PrivateMessageVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;


/**
 * @author Stylesmile
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FriendApplyServiceImpl implements IFriendApplyService {

    private final PrivateMessageServiceImpl privateMessageService;
    private final FriendApplyMapper friendApplyMapper;
    private final SensitiveFilterUtil sensitiveFilterUtil;
    private final IMClient imClient;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addFriendApply(AddFriendApplyDTO addFriendApplyDTO) {
        long friendId = addFriendApplyDTO.getFriendId();
        long userId = SessionContext.getSession().getUserId();
        if (userId == friendId) {
            throw new GlobalException(ResultCode.PROGRAM_ERROR, "不允许添加自己为好友");
        }
        sendFriendApplyMessage(addFriendApplyDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void friendApplyReply(AddFriendApplyDTO addFriendApplyDTO) {
        long friendId = addFriendApplyDTO.getFriendId();
        long userId = SessionContext.getSession().getUserId();
        if (userId == friendId) {
            throw new GlobalException(ResultCode.PROGRAM_ERROR, "不允许添加自己为好友");
        }
        //好友申请消息回复
        friendApplyReplyMessage(addFriendApplyDTO);
    }

    /**
     * 发送好友消息
     *
     * @param addFriendApplyDTO 好友申请信息
     */
    public void sendFriendApplyMessage(AddFriendApplyDTO addFriendApplyDTO) {
        long friendId = addFriendApplyDTO.getFriendId();
        UserSession session = SessionContext.getSession();
        long userId = session.getUserId();
        // 过滤消息内容
        String content = sensitiveFilterUtil.filter(addFriendApplyDTO.getReason());
        Date date = new Date();

        PrivateMessageVO privateMessageVO = PrivateMessageVO.builder()
                .type(MessageType.ADD_FRIEND_APPLY.code())
                .content(content)
                .sendId(userId)
                .recvId(friendId)
                .status(MessageStatus.UNSEND.code())
                .sendTime(date)
                .build();
        // 推送消息
        IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>();
        sendMessage.setSender(new IMUserInfo(userId, session.getTerminal()));
        sendMessage.setRecvId(privateMessageVO.getRecvId());
        sendMessage.setSendToSelf(true);
        sendMessage.setData(privateMessageVO);
        sendMessage.setSendResult(true);

        IMSendInfo<Object> sendInfo = new IMSendInfo<>();
        sendInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
        sendInfo.setData(sendMessage.getData());

        // 发消息
        imClient.sendPrivateMessage(sendMessage);
        log.debug("发送私聊消息，发送id:{},接收id:{}，内容:{}", userId, privateMessageVO.getRecvId(), privateMessageVO.getContent());

        PrivateMessage msg = PrivateMessage.builder()
                .type(MessageType.ADD_FRIEND_APPLY.code()).sendTime(date)
                .content(content).sendId(userId).recvId(friendId)
                .status(MessageStatus.UNSEND.code())
                .build();
        // 保存消息
        privateMessageService.save(msg);

        FriendApply friendApply = FriendApply.builder().createTime(LocalDateTime.now()).sendId(userId).recvId(friendId)
                .status(FriendApplyStatus.APPLYING).content(content).build();
        // 保存好友申请
        this.save(friendApply);
    }

    /**
     * 好友申请消息回复
     *
     * @param addFriendApplyDTO 好友申请信息
     */
    public void friendApplyReplyMessage(AddFriendApplyDTO addFriendApplyDTO) {
        long friendId = addFriendApplyDTO.getFriendId();
        UserSession session = SessionContext.getSession();
        long userId = session.getUserId();
        // 过滤消息内容
        String content = sensitiveFilterUtil.filter(addFriendApplyDTO.getReason());
        Date date = new Date();
        LocalDateTime now = LocalDateTime.now();

        PrivateMessageVO privateMessageVO = PrivateMessageVO.builder()
                .type(MessageType.ADD_FRIEND_APPLY_REPLY.code())
                .content(content)
                .sendId(userId)
                .recvId(friendId)
                .status(MessageStatus.UNSEND.code())
                .sendTime(date)
                .build();

        // 推送消息
        IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>();
        sendMessage.setSender(new IMUserInfo(userId, session.getTerminal()));
        sendMessage.setRecvId(privateMessageVO.getRecvId());
        sendMessage.setSendToSelf(true);
        sendMessage.setData(privateMessageVO);
        sendMessage.setSendResult(true);

        IMSendInfo<Object> sendInfo = new IMSendInfo<>();
        sendInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
        sendInfo.setData(sendMessage.getData());

        // 给mqtt 发消息
        imClient.sendPrivateMessage(sendMessage);
        log.debug("发送私聊消息，发送id:{},接收id:{}，内容:{}", userId, privateMessageVO.getRecvId(), privateMessageVO.getContent());

        PrivateMessage msg = PrivateMessage.builder()
                .type(MessageType.ADD_FRIEND_APPLY.code())
                .content(content)
                .sendId(userId)
                .recvId(friendId)
                .status(MessageStatus.UNSEND.code())
                .sendTime(date)
                .build();
        // 保存消息
        privateMessageService.save(msg);
    }

    public void save(FriendApply friendApply) {
        friendApplyMapper.insert(friendApply);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addFriend(AddFriendDTO addFriendDTO) {
        long userId = SessionContext.getSession().getUserId();
        long friendId = addFriendDTO.getFriendId();
        if (userId == friendId) {
            throw new GlobalException(ResultCode.PROGRAM_ERROR, "不允许添加自己为好友");
        }

        // 互相绑定好友关系
        FriendServiceImpl proxy = (FriendServiceImpl) AopContext.currentProxy();
        proxy.bindFriend(userId, friendId);
        proxy.bindFriend(friendId, userId);
        log.info("添加好友，用户id:{},好友id:{}", userId, friendId);
        // 更新好友申请状态
        updateFriendApplyStatus(addFriendDTO.getFriendApplyId());
    }

    /**
     * 修改好友申请状态
     *
     * @param friendApplyId id
     */
    @Override
    public void updateFriendApplyStatus(Long friendApplyId) {
        FriendApply friend = FriendApply.builder()
                .status(FriendApplyStatus.COMPLETE)
                .build();
        QueryWrapper<FriendApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", friendApplyId);
        friendApplyMapper.update(friend, queryWrapper);
    }

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.printf(now.toString());
    }
}
